﻿using Common.Infrastructure;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Common.EF
{
    public interface ICommonRepository
    {
        Task<T> GetEntityAsync<T>(string id, params string[] includes)
           where T : EntityBase, new();

        Task<T> GetEntityAsync<T>(ApiParam apiParam, Expression<Func<T, bool>> predicate, string[] includes = null)
           where T : EntityBase, new();

        Task<List<T>> GetEntitiesAsync<T>(List<string> ids, string[] includes = null)
           where T : EntityBase, new();

        Task<List<T>> GetEntitiesAsync<T>(ApiParam apiParam, List<string> ids, string[] includes = null)
           where T : EntityBase, new();

        Task<List<T>> GetEntitiesAsync<T>(Expression<Func<T, bool>> predicate, string[] includes = null)
           where T : EntityBase, new();

        Task<List<T>> GetEntitiesAsync<T>(ApiParam apiParam, Expression<Func<T, bool>> predicate, string[] includes = null)
           where T : EntityBase, new();

        Task<List<T>> GetOrderEntitiesAsync<T>(ApiParam apiParam, Expression<Func<T, bool>> predicate, string[] includes = null)
           where T : EntityBase, new();

        Task<List<T>> GetOrderEntitiesAsync<T>(ApiParam apiParam, Expression<Func<T, bool>> predicate, Dictionary<string, int> orders, string[] includes = null)
           where T : EntityBase, new();

        Task<ApiPagedResult<T>> GetOrderPageEntitiesAsync<T>(ApiOrderPageParam apiOrderPageParam, Expression<Func<T, bool>> predicate, string[] includes = null)
          where T : EntityBase, new();

        Task<ApiPagedResult<T>> GetOrderPageEntitiesAsync<T>(Expression<Func<T, bool>> predicate, Dictionary<string, int> orders, int startIndex, int pageSize, string[] includes = null)
           where T : EntityBase, new();

        Task<ApiPagedResult<T>> GetOrderPageEntitiesAsync<T>(ApiOrderPageParam apiOrderPageParam, Expression<Func<T, bool>> predicate, Dictionary<string, int> orders, int startIndex, int pageSize, string[] includes = null)
           where T : EntityBase, new();

        Task<int> GetCountAsync<T>(ApiParam apiParam, Expression<Func<T, bool>> predicate)
         where T : EntityBase, new();

        Task<decimal> GetSumAsync<T>(ApiParam apiParam, Expression<Func<T, bool>> predicate, Expression<Func<T, decimal>> sumExpression)
           where T : EntityBase, new();

        Task<List<IGrouping<S, T>>> GetGroupByAsync<T, S>(ApiParam apiParam, Expression<Func<T, bool>> predicate, Expression<Func<T, S>> groupByExpression)
           where T : EntityBase, new();

        T GetEntity<T>(string id, params string[] includes)
           where T : EntityBase, new();

        T GetEntity<T>(ApiParam apiParam, Expression<Func<T, bool>> predicate, string[] includes = null)
           where T : EntityBase, new();

        List<T> GetEntities<T>(List<string> ids, string[] includes = null)
           where T : EntityBase, new(); 

        List<T> GetEntities<T>(Expression<Func<T, bool>> predicate, string[] includes = null)
           where T : EntityBase, new();

        List<T> GetEntities<T>(ApiParam apiParam, Expression<Func<T, bool>> predicate = null, string[] includes = null)
           where T : EntityBase, new();

        List<T> GetOrderEntities<T>(Expression<Func<T, bool>> predicate, string[] includes = null)
          where T : EntityBase, new();

       List<T> GetOrderEntities<T>(ApiParam apiParam, Expression<Func<T, bool>> predicate = null, string[] includes = null)
           where T : EntityBase, new();

        List<T> GetOrderEntities<T>(ApiParam apiParam, Expression<Func<T, bool>> predicate, Dictionary<string, int> orders, string[] includes = null)
           where T : EntityBase, new();

        ApiPagedResult<T> GetOrderPageEntities<T>(ApiOrderPageParam apiOrderPageParam, Expression<Func<T, bool>> predicate = null, string[] includes = null)
          where T : EntityBase, new();

        ApiPagedResult<T> GetOrderPageEntities<T>(Expression<Func<T, bool>> predicate, Dictionary<string, int> orders, int startIndex, int pageSize, string[] includes = null)
           where T : EntityBase, new();

        ApiPagedResult<T> GetOrderPageEntities<T>(ApiOrderPageParam apiOrderPageParam, Expression<Func<T, bool>> predicate, Dictionary<string, int> orders, int startIndex, int pageSize, string[] includes = null)
           where T : EntityBase, new();

        int GetCount<T>(ApiParam apiParam, Expression<Func<T, bool>> predicate)
         where T : EntityBase, new();

        decimal GetSum<T>(ApiParam apiParam, Expression<Func<T, bool>> predicate, Expression<Func<T, decimal>> sumExpression)
           where T : EntityBase, new();

        List<IGrouping<S, T>> GetGroupBy<T, S>(ApiParam apiParam, Expression<Func<T, bool>> predicate, Expression<Func<T, S>> groupByExpression)
            where T : EntityBase, new();

        void AddEntity<T>(T entity)
           where T : EntityBase, new();

        void AddEntities<T>(List<T> entities)
           where T : EntityBase, new();

        void UpdateEntity<T>(T entity, params string[] updateProperies)
           where T : EntityBase, new();

        void UpdateEntities<T>(List<T> entities, params string[] updateProperies)
           where T : EntityBase, new();

        void SaveEntity<T>(T entity, params string[] updateProperies)
           where T : EntityBase, new();

        void SaveEntities<T>(List<T> entities, params string[] updateProperies)
           where T : EntityBase, new();

        void DeleteEntity<T>(string id)
           where T : EntityBase, new();

        void DeleteEntity<T>(List<string> ids)
           where T : EntityBase, new();

        void DeleteEntity<T>(Expression<Func<T, bool>> predicate)
           where T : EntityBase, new();

        void DeleteEntityByCommit<T>(ApiParam apiParam, Expression<Func<T, bool>> predicate)
         where T : EntityBase, new();

        void UpdateEntitiesByByCommit<T>(ApiParam apiParam, Expression<Func<T, bool>> predicate, Expression<Func<T, T>> updateExpression)
         where T : EntityBase, new();

        void ExecuteReaderByContext(ApiParam apiParam, CommandType commandType, string sql, ApiDbParameter[] parameters, Action<DbDataReader> readerAction);

        void ExecuteNonQueryByContext(ApiParam apiParam, CommandType commandType, string sql, ApiDbParameter[] parameters);

        Task DatabaseMigrateAsync(DateTime? beginTime, DateTime? endTime);

        List<string> GetEntityIds(IDParam model);

        Task<int> SaveChangesAsync(CancellationToken cancellationToken = default);

        int SaveChanges();

        string GetContextCodeById(string id);

        void RemoveDistributeCacheKeys();

        Task CommitChangesAsync(Action func);

        Task CommitChangesByFuncAsync(Func<Task> func);

        ApiParam GetApiParamById(string id);

        ApiParam GetApiParamByIds(List<string> ids);

        ApiParam GetApiParamByEntity<T>(T entity) 
            where T : EntityBase, new();

        ApiParam GetApiParamByEntities<T>(List<T> entitis)
            where T : EntityBase, new();

        void CommitChanges(Action func);

        void Dispose();
    }
}
